package sharefolder

import (
	"fmt"
	"github.com/pkg/errors"
	"gitlab.local/TerraMaster/tos-modules/core/tosutils"
	"gitlab.local/TerraMaster/tos-modules/database/sqlitemodel"
	"gitlab.local/TerraMaster/tos-modules/directory"
	"gitlab.local/golibrary/linux"
	"gitlab.local/golibrary/utils"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

func (f *Folder) GetIsoList() []sqlitemodel.Share {
	result := make([]sqlitemodel.Share, 0)
	for _, item := range f.dirService.GetByType("ISO") {
		result = append(result, item)
	}
	return result
}

// getIsoFolderId 获取iso挂载文件夹id
func (f *Folder) getIsoFolderId(mntPath string) int {
	for _, v := range f.GetIsoList() {
		if v.MntPath == mntPath {
			return v.FolderId
		}
	}
	return 0
}

// CreateIsoFolder
// sqlitemodel.Share 中的 Extend 存放iso文件路径
func (f *Folder) CreateIsoFolder(option sqlitemodel.Share) error {
	if !utils.Exists(option.Extend) {
		return errors.New("invalid iso file")
	}
	ISOROOT := linux.GetMainVolume()
	if ISOROOT == "" {
		return errors.New("invalid volume")
	}
	ISOROOT = filepath.Join(ISOROOT, "@iso")
	if !utils.Exists(ISOROOT) {
		_ = utils.MkdirPerm(ISOROOT, os.ModePerm)
	}
	//判断共享文件夹是否存在
	if f.IsExistsFolder(option.FolderName) {
		return FileExists
	}
	option.Type = "ISO"
	option.Owner = GetFirstAdmin()
	option.Device = "iso"
	option.MntPath = filepath.Join(ISOROOT, option.FolderName)
	mntPath, err := f.dirService.Create(option.Owner, directory.CreateFolder{Share: option})
	if err != nil {
		return err
	}
	_, err = utils.ShellExec(fmt.Sprintf(`mount -o loop,iocharset=utf8 -t udf,iso9660 '%s' '%s'`, option.Extend, option.MntPath))
	if err != nil {
		if fid := f.getIsoFolderId(mntPath); fid > 0 {
			_ = f.DeleteIsoFolder(fid)
		}
	} else {
		//设置acl权限
		_ = f.aclService.InitExternalAcl(option.MntPath, "iso", "r-x")
	}
	//重启全部文件服务服务
	tosutils.ReStartBaseService("")
	return err
}

func (f *Folder) DeleteIsoFolder(id int) error {
	var folder interface{}
	for _, item := range f.GetIsoList() {
		if item.FolderId == id {
			folder = item
			break
		}
	}
	if folder == nil {
		return errors.New("invalid folder id")
	}
	folderInfo := folder.(sqlitemodel.Share)
	if linux.GetDeviceInfoByPath(folderInfo.MntPath) != nil {
		_ = os.Chdir("/")
		_, _ = utils.ShellExec(fmt.Sprintf(`fuser -k '%s'`, folderInfo.MntPath))
		_, _ = utils.ShellExec(fmt.Sprintf(`umount -v '%s'`, folderInfo.MntPath))
	}
	return f.DeleteFolder(id)
}

func (f *Folder) existIsoFile(name string) bool {
	isoList := f.GetIsoList()
	for _, folder := range isoList {
		if folder.Extend == name {
			return true
		}
	}
	return false
}

// ScanIsoFiles 扫描共享文件夹前三级中的iso文件
func (f *Folder) ScanIsoFiles() (result []string) {
	result = make([]string, 0)
	folderList := f.GetFolderList("")
	for _, folder := range folderList {
		if !utils.Exists(folder.MntPath) {
			continue
		}
		result = append(result, f.scanIsoFiles(folder.MntPath, 3)...)
	}
	return
}

func (f *Folder) scanIsoFiles(root string, level int) (result []string) {
	result = make([]string, 0)
	_ = fs.WalkDir(os.DirFS(root), ".", func(path string, d fs.DirEntry, err error) error {
		if path == "." {
			return nil
		}
		if d.IsDir() {
			if len(strings.Split(path, "/")) > level {
				return fs.SkipDir
			}
		} else {
			if strings.HasSuffix(d.Name(), ".iso") || strings.HasSuffix(d.Name(), ".ISO") {
				if !f.existIsoFile(filepath.Join(root, path)) {
					result = append(result, filepath.Join(root, path))
				}
			}
		}
		return nil
	})
	return
}

// GetFirstAdmin 获取超级管理员名
func GetFirstAdmin() string {
	result := os.Getenv("admin")
	if result == "" {
		result = "admin"
	}
	return result
}
